package com.dgut.controller;

import com.dgut.entity.Administrator;
import com.dgut.service.AdminService;
import com.dgut.service.TokenService;
import com.dgut.service.UserService;
import com.dgut.service.impl.AdminServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.*;
import com.dgut.Config.AppProperties;
import com.dgut.Dto.LoginDto;
import com.dgut.Vo.LoginVo;
import com.dgut.Vo.UserVo;
import com.dgut.util.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.HashMap;
import java.util.Optional;

@RequiredArgsConstructor
@RestController
@RequestMapping("/authorize")
public class AuthorizeController {

    private final JwtUtil jwtUtil;

    @Autowired
    AppProperties appProperties;

    @Autowired
    AdminService adminService;

    @Autowired
    TokenService tokenService;

    @Autowired
    UserService userService;

    @PostMapping("/user/token")
    public UserVo userToken(@Valid @RequestBody LoginDto loginDTO, HttpServletResponse response) throws AccessDeniedException, IOException {
        //public LoginVo token(){
        //根据用户名去数据库获取账号信息
        com.dgut.entity.User user = userService.getUserByStuId(loginDTO.getUsername());

        //返回给前端的对象，初始化为null
        UserVo userVo = null;
        //查询数据库
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++");
        System.out.println("/token: " + loginDTO.getUsername()+": "+loginDTO.getPassword());
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++");
        System.out.println(user);
        //如果查询得到账号信息
        if(user != null){
            //比较账号密码
            if(loginDTO.getUsername().equals(user.getStuId()) && loginDTO.getPassword().equals(user.getPassword())){
                //new一个用于创建token的user
                User userToken = new User(user.getStuId(), loginDTO.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
                // 分界线---------------------------以下开始给予token
                //获取accessToken和refreshToken
                String accessToken = tokenService.createAccessToken(userToken);
                //String refreshToken = jwtUtil.createRefreshToken(user);
                //LoginVo loginVo = new LoginVo(accessToken, refreshToken);
                //将用户名及accessToken交给loginVo
                userVo = new UserVo(user.getStuId(), user.getName(), user.getSchool(), user.getType(), accessToken);

                //测试：解密token信息
                //Optional<Claims> claims = jwtUtil.parseClaims(accessToken, jwtUtil.getKey());
                //System.out.println(claims);
            }else{
                System.out.println("密码错误");
                response = setResponse(response, 10002, "密码错误");
                //throw new AccessDeniedException("密码错误");
            }
        }else{
            System.out.println("账号不存在");
            response = setResponse(response, 10001, "账号不存在");
        }
        //User user = new User(administrator.getAccount(), loginDTO.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_USER"));
        return userVo;
    }


    @PostMapping("/admin/token")
    public LoginVo token(@Valid @RequestBody LoginDto loginDTO, HttpServletResponse response) throws AccessDeniedException, IOException {
    //public LoginVo token(){
        //根据用户名去数据库获取账号信息
        Administrator administrator = adminService.getAdministratorByAccount(loginDTO.getUsername());
        //返回给前端的对象，初始化为null
        LoginVo loginVo = null;
        //查询数据库
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++");
        System.out.println("/token: " + loginDTO.getUsername()+": "+loginDTO.getPassword());
        System.out.println("++++++++++++++++++++++++++++++++++++++++++++++++++");
        System.out.println(administrator);
        //如果查询得到账号信息
        if(administrator != null){
            //比较账号密码
            if(loginDTO.getUsername().equals(administrator.getAccount()) && loginDTO.getPassword().equals(administrator.getPassword())){
                //new一个用于创建token的user
                User user = new User(administrator.getAccount(), loginDTO.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_USER"));
                // 分界线---------------------------以下开始给予token
                //获取accessToken和refreshToken
                String accessToken = tokenService.createAccessToken(user);
                //String refreshToken = jwtUtil.createRefreshToken(user);
                //LoginVo loginVo = new LoginVo(accessToken, refreshToken);
                //将用户名及accessToken交给loginVo
                loginVo = new LoginVo(administrator.getAccount(), accessToken);
                //LoginVo loginVo = new LoginVo(administrator.getAccount(), accessToken);
                //测试：解密token信息
                //Optional<Claims> claims = jwtUtil.parseClaims(accessToken, jwtUtil.getKey());
                //System.out.println(claims);
            }else{
                System.out.println("密码错误");
                response = setResponse(response, 10002, "密码错误");
                //throw new AccessDeniedException("密码错误");
            }
        }else{
            System.out.println("账号不存在");
            response = setResponse(response, 10001, "账号不存在");
        }
        //User user = new User(administrator.getAccount(), loginDTO.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_USER"));
        return loginVo;
    }

    //public String tokenIsValid(@RequestParam String accessToken){
    @GetMapping("/token/isValid")
    //@CrossOrigin(origins = "*",maxAge = 3600)
    public String tokenIsValid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String accessToken = tokenService.getAccessToken(request);
        System.out.println(accessToken);
        if (accessToken == null){
            return "accessToken is NULL";
        }
        Boolean valid = tokenService.isAccessTokenValid(accessToken);
        //Boolean valid = true;
        System.out.println(valid);
        if(valid == true){
            return "true";
        } else {
            //response = setResponse(response, 10004, "无效");
            return "false";
        }
    }
    //
    //@PostMapping("/token/refresh")
    //public LoginVo refreshToken(@RequestHeader(name = "Authorization") String authorization, @RequestParam String refreshToken) throws Exception {
    //    val accessToken = authorization.replace(appProperties.getJwt().getPrefix(), "");
    //    //accessToken验证通过且refreshToken验证通过且没过期
    //    if(jwtUtil.validateRefreshToken(refreshToken) && jwtUtil.validateWithoutExpiration(accessToken)) {
    //        return new LoginVo(jwtUtil.buildAccessTokenWithRefreshToken(refreshToken), refreshToken);
    //    } throw new AccessDeniedException("Bad Credentials");
    //}
    //
    ////测试
    //@PostMapping("/hello")
    //public String hello(HttpServletRequest request) {
    //    String accessToken = tokenService.getAccessToken(request);
    //    System.out.println("Hello");
    //    Optional<Claims> claims = jwtUtil.parseClaims(accessToken, jwtUtil.getKey());
    //    System.out.println("claims: " + claims);
    //    return "hello security";
    //}

    //设置response返回值
    public HttpServletResponse setResponse(HttpServletResponse response, long status, String message) throws IOException {
        HashMap map = new HashMap();
        map.put("status", status);
        map.put("message", message);
        ObjectMapper objectMapper = new ObjectMapper();
        response.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(map));
        return response;
    }

}
